#include <kaleidoscope/common/decorate.hpp>
//=====================================================================
#include <sstream>
#include <boost/lexical_cast.hpp>
#include <atma/assert.hpp>
//=====================================================================
#include <kaleidoscope/common/symbol_ids.hpp>
#include <kaleidoscope/frontend/syntactical_analysis/marshall.hpp>
//=====================================================================
using namespace atma;
using namespace atma::sooty;
//=====================================================================

std::string kal::decorate_function(sooty::const_parseme_ptr_ref node)
{
	// special logic for main()
	if (node->value.string == "main")
		return "main";
		
	// fucntions are preceded by "F"
	std::stringstream decorated_name;
	decorated_name << "F";
	
	// name
	const_parseme_ptr_ref name = marshall::function::name(node);
	decorated_name
		<< name->value.string.size()
		<< name->value.string;
	
	// return value
	decorated_name << decorate_type(marshall::function::return_type(node));
	
	// parameters
	parseme_ptr_ref pl = marshall::function::parameter_list(node);
	for (parseme_container::iterator i = pl->children.begin(); i != pl->children.end(); ++i)
	{
		decorated_name << decorate_type(marshall::parameter::type(*i));
	}
	
	return decorated_name.str();
}

std::string kal::decorate_type(atma::sooty::const_parseme_ptr_ref n)
{
	using namespace kal;
	
	ATMA_ASSERT
		(
			   n->id == ids::identifier
			|| n->id == ids::int_type
		);
	
	if (n->id == ids::int_type)
	{
		return "Ti";
	}
	else // if (n->id == ids::identifier)
	{
		return std::string("T")
			+ boost::lexical_cast<std::string>(n->value.string.size())
			+ n->value.string;
	}
}


std::string kal::undecorated_type(atma::sooty::const_parseme_ptr_ref n)
{
	ATMA_ASSERT
		(
			n->id == ids::identifier
			|| n->id == ids::int_type
		);
		
	if (n->id == ids::identifier)
		return "int";
	else // if (n->id == ids::identifier)
		return n->value.string;
}
